package weaver.limitCurrent;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.GCONST;
import weaver.hrm.User;

public class LimitCurrentFilter implements Filter {
  public static String[] passUrls = null;
  public static String[] passUsers = null;

  public static AtomicInteger sleepcount = new AtomicInteger(0);
  
  private static final String dklc_e8 = "/workflow/request/ManageRequest";
  
  private static final String dklc2_e8 = "/workflow/request/ViewRequest";
  
  private static final String dklc3_e8 = "/workflow/request/WorkflowViewSignMore.jsp";
  
  private static final String tjlc_e8 = "/workflow/request/RequestOperation.jsp";
  
  private static final String tjlc_e9 = "/api/workflow/reqform/requestOperation";
  
  private static final String dklc_e9 = "/api/workflow/reqform/loadForm";
  
  private static final String dklc2_e9 = "/api/workflow/reqform/getRequestLogList";
  
  public void doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) throws ServletException, IOException {
    HttpServletRequest localHttpServletRequest = (HttpServletRequest)paramServletRequest;
    HttpServletResponse localHttpServletResponse = (HttpServletResponse)paramServletResponse;
    //对特殊用户进行放行
    User user = (User) localHttpServletRequest.getSession().getAttribute("weaver_user@bean");
   if (user!=null){
     for (String passUser : passUsers) {
       if (passUser.equals(user.getLoginid())){
         paramFilterChain.doFilter(paramServletRequest, paramServletResponse);
         return;
       }
     }
   }
    //对特殊接口进行放行
    String requestUri = localHttpServletRequest.getRequestURI();
    for (String passUrl : passUrls) {
        if (passUrl.indexOf(requestUri)>-1){
          paramFilterChain.doFilter(paramServletRequest, paramServletResponse);
          return;
        }
    }
    boolean isE8 = requestUri.contains(".jsp");
    if (isE8 || !requestUri.contains(".")) {
      if (isE8) {
        if (requestUri.indexOf("/workflow/request/ManageRequest") > -1 || requestUri.indexOf("/workflow/request/RequestOperation.jsp") > -1 || requestUri.indexOf("/workflow/request/ViewRequest") > -1 || requestUri.indexOf("/workflow/request/WorkflowViewSignMore.jsp") > -1) {
          String requestid = paramServletRequest.getParameter("requestid");
          requestUri = String.valueOf(requestUri) + requestid;
        } 
      } else if (requestUri.indexOf("/api/workflow/reqform/loadForm") > -1 || requestUri.indexOf("/api/workflow/reqform/requestOperation") > -1 || requestUri.indexOf("/api/workflow/reqform/getRequestLogList") > -1) {
        String requestid = paramServletRequest.getParameter("requestid");
        requestUri = String.valueOf(requestUri) + requestid;
      } 
      String uri = MD5.MD5Encode(requestUri);
      if (uri == null)
        uri = "null"; 
      long nowtime = System.nanoTime();
      StringBuilder sb = new StringBuilder(uri);
      sb.append(nowtime);
      String uritime = MD5.MD5Encode(sb.toString());
      if (uritime == null)
        uritime = "null";
      String content=null;
      try {
        if (LimitCurrentService.isLimit(uri)) {
          if (sleepcount.intValue() >= LimitCurrentService.sleepcount) {
            LimitCurrentService.putRequestCount(uri);
            LimitCurrentService.putRequestBean(uri, uritime, nowtime);
            String result = "system is busy,please try it later!  weaver_performance";
            if (isAjaxRequest(localHttpServletRequest)) {
              localHttpServletResponse
                .setContentType("text/text");
              PrintWriter out = localHttpServletResponse
                .getWriter();
              out.print(result);
              //10分钟之内限流了不输出此日志,频繁输出导致IO压力大
              content=result + ":----" + requestUri;
              String contentHash=String.valueOf(content.hashCode());
              if (!ExpireConcurrentHashMap.checkCacheName(contentHash)){
                (new BaseBean()).writeLog(content);
              }
              out.flush();
              out.close();
              return;
            } 
            localHttpServletRequest.getRequestDispatcher(
                "/limitCurr/limit.jsp").forward(
                (ServletRequest)localHttpServletRequest, 
                (ServletResponse)localHttpServletResponse);
            content=result + ":----" + requestUri;
            String contentHash=String.valueOf(content.hashCode());
            if (!ExpireConcurrentHashMap.checkCacheName(contentHash)){
              (new BaseBean()).writeLog(content);
            }
            return;
          } 
          sleepcount.incrementAndGet();
          try {
            Thread.sleep(5000L);
          } catch (InterruptedException e) {
            e.printStackTrace();
          } 
          LimitCurrentService.putRequestCount(uri);
          LimitCurrentService.putRequestBean(uri, uritime, nowtime);
          paramFilterChain.doFilter((ServletRequest)localHttpServletRequest, 
              (ServletResponse)localHttpServletResponse);
          sleepcount.decrementAndGet();
          return;
        } 
        LimitCurrentService.putRequestCount(uri);
        LimitCurrentService.putRequestBean(uri, uritime, nowtime);
        paramFilterChain.doFilter((ServletRequest)localHttpServletRequest, (ServletResponse)localHttpServletResponse);
      } finally {
        //处理完之后记录一下 30秒后过期
        ExpireConcurrentHashMap.put(content,30);
        //防止内存溢出
        if(ExpireConcurrentHashMap.size() > 5000){
          ExpireConcurrentHashMap.removeAll();
        }
        LimitCurrentService.removeRequestCount(uri);
        LimitCurrentService.removeRequestBean(uri, uritime);
      } 
      return;
    } 
    paramFilterChain.doFilter((ServletRequest)localHttpServletRequest, 
        (ServletResponse)localHttpServletResponse);
  }
  
  public void init(FilterConfig paramFilterConfig) throws ServletException {
    BaseBean bb = new BaseBean();
    String passUrl = bb.getPropValue("LimitCurrent", "passUrl");
    String passUser = bb.getPropValue("LimitCurrent", "passUser");
    passUrls = passUrl.split(",");
    passUsers=passUser.split(",");
  }
  
  public void destroy() {}
  
  private boolean isAjaxRequest(HttpServletRequest request) {
    String accept = request.getHeader("accept");
    String xRequestedWith = request.getHeader("X-Requested-With");
    return !((accept == null || accept.indexOf("application/json") == -1) && (xRequestedWith == null || xRequestedWith
      .indexOf("XMLHttpRequest") == -1));
  }

}
